﻿using System;
using Microsoft.Xna.Framework;

namespace Serious
{
    public struct LineSegment2
    {
        public Vector2 P1;
        public Vector2 P2;

        public LineSegment2(Vector2 p1, Vector2 p2)
        {
            P1 = p1;
            P2 = p2;
        }

        public Rectangle2 Bounds
        {
            get
            {
                return Rectangle2.FromPoints(P1, P2);
            }
        }

        public Single Length
        {
            get
            {
                return Vector2.Distance(P1, P2);
            }
        }

        public Single Slope (int dimension)
        {
            if (dimension == 0)
            {
                return (P2.X - P1.X) / (P2.Y - P1.Y);
            }
            else if (dimension == 1)
            {
                return (P2.Y - P1.Y) / (P2.X - P1.X);
            }
            else
            {
                throw new ArgumentException("dimension must be either 0 or 1 for a 2-dimensional linesegment");
            }
        }
        
        public void Translate(Vector2 offset)
        {
            P1 += offset;
            P2 += offset;
        }

        public static LineSegment2 operator +(LineSegment2 lineSegment, Vector2 offset)
        {
            lineSegment.Translate(offset);
            return lineSegment;
        }
        public static LineSegment2 operator -(LineSegment2 lineSegment, Vector2 offset)
        {
            lineSegment.Translate(-offset);
            return lineSegment;
        }

        // FIXME these functions go against the "spirit" (lolol, butthead)
        // of the LineSegment. That is, that there is no guaranteed order
        // to P1 and P2. BUT i like these functons which is why im hesitant
        // to get rid of them
        /*
        public Vector2 PointAlongLengthRel (Single n)
        {
            return Vector2.Lerp(P1, P2, Math.Min(Math.Max(0.0f, n), 1.0f));
        }
        public Vector2 PointAlongLength (Single n)
        {
            return PointAlongLengthRel(n / Length);
        }
        */

        public static Vector2? Intersection(LineSegment2 line1, LineSegment2 line2, out Single ua, out Single ub)
        {
            Single x1 = line1.P1.X;
            Single y1 = line1.P1.Y;
            Single x2 = line1.P2.X;
            Single y2 = line1.P2.Y;

            Single x3 = line2.P1.X;
            Single y3 = line2.P1.Y;
            Single x4 = line2.P2.X;
            Single y4 = line2.P2.Y;

            Single ud = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
            if (ud == 0.0f)
            {
                ua = ub = 0.0f;
                return null;
            }

            ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ud;
            ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / ud;

            if (ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f)
            {
                return Vector2.Lerp(line1.P1, line1.P2, ua);
            }
            else
            {
                return null;
            }
        }
    }
}
